package io.github.iogogogo.commons.collection;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;

/**
 * Created by tao.zeng on 2024/11/7.
 */
public class MapUtils {

    /**
     * Sort by key map.
     *
     * @param <K> the type parameter
     * @param <V> the type parameter
     * @param map the map
     * @return the map
     */
    public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map) {
        // 这里使用了guava简化了map对象的创建，没有guava直接使用 new LinkedHashMap<>();
        Map<K, V> result = Maps.newLinkedHashMap();
        map.entrySet().stream()
                .sorted(Map.Entry.comparingByKey()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    /**
     * Sort reversed by key map.
     *
     * @param <K> the type parameter
     * @param <V> the type parameter
     * @param map the map
     * @return the map
     */
    public static <K extends Comparable<? super K>, V> Map<K, V> sortReversedByKey(Map<K, V> map) {
        Map<K, V> result = Maps.newLinkedHashMap();
        map.entrySet().stream()
                .sorted(Map.Entry.<K, V>comparingByKey()
                        .reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    /**
     * Sort by value map.
     *
     * @param <K> the type parameter
     * @param <V> the type parameter
     * @param map the map
     * @return the map
     */
    public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
        Map<K, V> result = Maps.newLinkedHashMap();
        map.entrySet().stream()
                .sorted(Map.Entry.comparingByValue()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    /**
     * Sort reversed by value map.
     *
     * @param <K> the type parameter
     * @param <V> the type parameter
     * @param map the map
     * @return the map
     */
    public static <K, V extends Comparable<? super V>> Map<K, V> sortReversedByValue(Map<K, V> map) {
        Map<K, V> result = Maps.newLinkedHashMap();
        map.entrySet().stream()
                .sorted(Map.Entry.<K, V>comparingByValue()
                        .reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    /**
     * Gets first key.
     *
     * @param <K> the type parameter
     * @param map the map
     * @return the first key
     */
    public static <K> K getFirstKey(Map<K, ?> map) {
        return map.keySet().iterator().next();
    }

    /**
     * Gets last key.
     *
     * @param <K> the type parameter
     * @param map the map
     * @return the last key
     */
    public static <K> K getLastKey(Map<K, ?> map) {
        Iterator<K> iterator = map.keySet().iterator();
        LinkedList<K> list = Lists.newLinkedList();
        while (iterator.hasNext()) {
            list.add(iterator.next());
        }
        return list.getLast();
    }

    /**
     * Gets first.
     *
     * @param <K> the type parameter
     * @param <V> the type parameter
     * @param map the map
     * @return the first
     */
    public static <K, V> Map.Entry<K, V> getFirst(Map<K, V> map) {
        return map.entrySet().iterator().next();
    }

    /**
     * Gets last.
     * <p>
     * 通过反射获取LinkedHashMap中的末尾元素：
     * <p>
     * 时间复杂度O(1)，访问tail属性
     *
     * @param <K> the type parameter
     * @param <V> the type parameter
     * @param map the map
     * @return the last
     * @throws IllegalAccessException the illegal access exception
     * @throws NoSuchFieldException   the no such field exception
     */
    @SuppressWarnings("unchecked")
    public static <K, V> Map.Entry<K, V> getLast(Map<K, V> map) throws IllegalAccessException, NoSuchFieldException {
        Field tail = map.getClass().getDeclaredField("tail");
        tail.setAccessible(true);
        return (Map.Entry<K, V>) tail.get(map);
    }
}
